package com.amumu.drama.common.modules.service.impl.payment.handler;

import cn.hutool.core.util.StrUtil;
import com.amumu.drama.common.commpont.transaction.TransactionHelper;
import com.amumu.drama.common.config.RedissonLockUtil;
import com.amumu.drama.common.constant.*;
import com.amumu.drama.common.modules.member.service.UmsMemberService;
import com.amumu.drama.common.modules.order.dto.OmsOrderDetail;
import com.amumu.drama.common.modules.order.dto.PrePayCreateDTO;
import com.amumu.drama.common.modules.order.dto.PrePayInfoDTO;
import com.amumu.drama.common.modules.order.manager.OrderManager;
import com.amumu.drama.common.modules.service.impl.payment.PaymentFactory;
import com.amumu.drama.common.modules.service.impl.payment.PaymentReq;
import com.amumu.drama.common.modules.service.impl.payment.PaymentResp;
import com.amumu.drama.mapper.UmsIntegrationChangeHistoryMapper;
import com.amumu.drama.model.OmsOrder;
import com.amumu.drama.model.UmsIntegrationChangeHistory;
import com.amumu.drama.model.UmsMember;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author sunzhuang
 * @date 2024/5/12 18:00
 * @slogan 天下风云出我辈, 一入代码岁月催
 * @desc 使用微丸积分进行支付
 */

@Slf4j
@Component
public class IntegrationPaymentHandler implements PaymentHandler {

    @Autowired
    private UmsMemberService memberService;


    @Autowired
    private RedissonLockUtil redissonLockUtil;

    @Autowired
    private OrderManager orderManager;

    @Autowired
    private UmsIntegrationChangeHistoryMapper integrationChangeHistoryMapper;

    @Override
    public String[] type() {
        return new String[]{
                PaymentFactory.getPayHandlerType(PayTypeEnum.WEIWAN_PAY, PayProviderEnum.WE_PLAYER, SourceTypeEnum.UNKNOWN),
                PaymentFactory.getPayHandlerType(PayTypeEnum.WEIWAN_PAY, PayProviderEnum.WE_PLAYER, SourceTypeEnum.APP),
                PaymentFactory.getPayHandlerType(PayTypeEnum.WEIWAN_PAY, PayProviderEnum.WE_PLAYER, SourceTypeEnum.PC),
        };
    }

    /**
     * 预支付
     *
     * @param prePayCreateDTO
     */
    @Override
    public PrePayInfoDTO prePay(PrePayCreateDTO prePayCreateDTO) {
        PrePayInfoDTO resp = new PrePayInfoDTO();
        resp.setStatus(true);
        return resp;
    }

    @Override
    public PaymentResp pay(PaymentReq param) {
        PaymentResp resp = new PaymentResp();
        resp.setPayStatusEnum(PayStatusEnum.WAIT_PAY);
        resp.setApplyTime(LocalDateTime.now());
        //用积分购买
        String lockKey = RedissonLockUtil.LOCK_ORDER_PAY_KEY_PREFIX + param.getUmsMember().getId();
        RLock lock = redissonLockUtil.lock(lockKey, TimeUnit.SECONDS, 5);
        lock.lock();
        try {
            TransactionHelper.INSTANCE.run(() -> {
                UmsMember member = memberService.getById(param.getUmsMember().getId());
                OmsOrderDetail orderDetail = param.getOrderDetail();
                BigDecimal integration = member.getIntegration();
                BigDecimal integrationAmount = orderDetail.getIntegrationAmount();
                if (integration.compareTo(integrationAmount) < 0) {
                    //更新订单状态为支付失败
                    resp.setPayStatusEnum(PayStatusEnum.FAIL);
                    resp.setRespMsg("积分余额不足，请确认～");
                    resp.setPayRemark("积分余额不足，余额:[" + integration + "],订单金额：[" + integrationAmount + "]");
                    resp.setApplyConfirmTime(LocalDateTime.now());
                } else {
                    BigDecimal balance = integration.subtract(integrationAmount);
                    //更新用户余额
                    memberService.updateIntegration(member.getId(), balance);
                    //记录积分使用记录
                    UmsIntegrationChangeHistory history = new UmsIntegrationChangeHistory();
                    history.setMemberId(member.getId());
                    history.setCreateTime(new Date());
                    history.setChangeType(1);
                    history.setChangeCount(integrationAmount);
                    history.setOperateMan(member.getNickname());
                    history.setOperateNote(StrUtil.format("下单：orderId[{}]", orderDetail.getId()));
                    history.setSourceType(0);
                    integrationChangeHistoryMapper.insert(history);
                    resp.setPayStatusEnum(PayStatusEnum.SUCCESS);
                    resp.setApplyConfirmTime(LocalDateTime.now());
                }
            });
            return resp;
        } catch (Throwable e) {
            resp.setPayStatusEnum(PayStatusEnum.FAIL);
            resp.setPayRemark(e.getMessage());
            log.error("支付失败，支付参数:{}", param, e);
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
        return resp;
    }

    /** 积分返回退款 */
    @Override
    public PaymentResp refund(PaymentReq param, OperateTypeEnum operateTypeEnum, Long operatorId) {
        OmsOrder omsOrder = orderManager.getOmsOrderHighly(param.getOmsOrder(), param.getOrderId(), null, null);
        log.info("积分退款申请：订单ID：{},支付类型：{}", omsOrder.getId(), omsOrder.getPayType());
        PaymentResp resp = new PaymentResp();
        resp.setPayStatusEnum(PayStatusEnum.REFUNDING);
        resp.setApplyTime(LocalDateTime.now());
        //返还用户积分
        String lockKey = RedissonLockUtil.LOCK_ORDER_PAY_KEY_PREFIX + omsOrder.getMemberId();
        RLock lock = redissonLockUtil.lock(lockKey, TimeUnit.SECONDS, 5);
        lock.lock();
        try {
            TransactionHelper.INSTANCE.run(() -> {
                UmsMember member = memberService.getById(omsOrder.getMemberId());
                BigDecimal integration = member.getIntegration();
                BigDecimal integrationAmount = omsOrder.getIntegrationAmount();

                BigDecimal balance = integration.add(integrationAmount);
                //更新用户余额
                memberService.updateIntegration(member.getId(), balance);
                //记录积分使用记录
                UmsIntegrationChangeHistory history = new UmsIntegrationChangeHistory();
                history.setMemberId(member.getId());
                history.setCreateTime(new Date());
                history.setChangeType(0);
                history.setChangeCount(integrationAmount);
                history.setOperateMan(operateTypeEnum.getType() + "_" + operatorId);
                history.setOperateNote(StrUtil.format("订单退款：orderId[{}]", omsOrder.getId()));
                history.setSourceType(1);
                integrationChangeHistoryMapper.insert(history);
                resp.setPayStatusEnum(PayStatusEnum.REFUND);
                resp.setApplyConfirmTime(LocalDateTime.now());
            });
            return resp;
        } catch (Throwable e) {
            resp.setPayStatusEnum(PayStatusEnum.LOG);
            resp.setApplyConfirmTime(LocalDateTime.now());
            resp.setPayRemark(e.getMessage());
            log.error("积分退款失败:{}", param, e);
        } finally {
            if (lock != null) {
                lock.unlock();
            }
        }
        return resp;
    }

}
